package com.xiaoyu.lanling.app

import `in`.srain.cube.app.init.InitializableMultiProcessSync
import `in`.srain.cube.app.init.InitializableOneWay
import `in`.srain.cube.cache.DiskFileUtils
import `in`.srain.cube.concurrent.AppThreads
import `in`.srain.cube.util.CLog
import `in`.srain.cube.util.log.LogEvent
import `in`.srain.cube.util.log.LogServant
import android.content.Context
import android.os.Build
import com.netease.nimlib.sdk.NIMClient
import com.netease.nimlib.sdk.SDKOptions
import com.netease.nimlib.sdk.auth.LoginInfo
import com.xiaoyu.base.AppConfig
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.log.AppPerformanceLogClient
import com.xiaoyu.base.utils.MMKVUtil
import com.xiaoyu.im.data.IMTokenData
import com.xiaoyu.im.datamodel.IMVendorType
import com.xiaoyu.im.datamodel.common.IMConstant
import java.io.File

class MultiProcessInitProcessor(val context: Context) : InitializableMultiProcessSync, InitializableOneWay {

    companion object {
        fun init(context: Context) {
            val processor = MultiProcessInitProcessor(context)
            processor.initiateSyncInMultiProcess()

            AppThreads.runOnInitThread {
                processor.initiateAsyncOneWay(context)
            }
        }
    }

    override fun initiateSyncInMultiProcess() {
        val logEvent = LogEvent("init-multi-process")
        logEvent.startTimeForKey("total-time")

        logEvent.startTimeForKey("init-mmkv")
        initMMKV()
        logEvent.endTimeForKey("init-mmkv")

        logEvent.startTimeForKey("init-user-data")
        UserData.getInstance().initiateSyncInMultiProcess()
        logEvent.endTimeForKey("init-user-data")

        logEvent.startTimeForKey("init-nim")
        initNIMClient()
        logEvent.endTimeForKey("init-nim")

        logEvent.endTimeForKey("total-time")
        AppPerformanceLogClient.instance.addLog(logEvent)
    }

    override fun initiateAsyncOneWay(context: Context?) {
        val logEvent = LogEvent("init-multi-process-async")
        logEvent.startTimeForKey("total-time")

        logEvent.startTimeForKey("init-log-servant")
        initLogServant()
        logEvent.endTimeForKey("init-log-servant")

        logEvent.endTimeForKey("total-time")
        AppPerformanceLogClient.instance.addLog(logEvent)
    }

    private fun initMMKV() {
        MMKVUtil.init(context)
    }

    private fun initNIMClient() {
        val vendorType = IMVendorType.NIM
        val tokenInfo = IMTokenData.getTokenInfo(vendorType)
        val loginInfo = if (tokenInfo.isEmpty) null else LoginInfo(tokenInfo.vendorUid, tokenInfo.token, AppConfig.neteaseAppKey())
        if (tokenInfo.isEmpty) {
            CLog.w(IMConstant.LOG_TAG, "%s auto login error because token empty", vendorType)
        }
        val options = SDKOptions()
        options.appKey = AppConfig.neteaseAppKey()
        options.disableAwake = disableAwakeForAndroidN()
        options.sdkStorageRootPath = DiskFileUtils.wantFilesPath(context, true) + File.separator + "IM" + File.separator + vendorType
        NIMClient.init(context, loginInfo, options)
    }

    private fun initLogServant() {
        // TODO(upload log)
        LogServant.getInstance().initiateAsyncOneWay(context)
        // LogServant.getInstance().setLogUploader(DefaultLogUploader.getInstance())
    }

    private fun disableAwakeForAndroidN(): Boolean {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
    }
}